import { useRef } from "react";
import get from "lodash/get";
import set from "lodash/set";
import { updateField, useForm } from "../context/metadata-context";
import eventBus, { useSubscribe } from "../eventBus";
import request from "../utils/request";
import { saveformDataObject } from "../../../components/Header/businessBtnUtils";
import { mergecalculateFormData } from "../../../apis/mergeFormData";

function _updateField({
  fieldPath,//字段code 主表为 fieldCode 子表为 groupCode.fieldCode
  tplData,
  rowIndex,
  data
}){
  
  if (~fieldPath.indexOf(".")) {//子表更新
    //更新子表字段
    const filedParts = fieldPath.split(".");

    if (filedParts.length === 2) {

      let tableCode = filedParts[0];//子表code
      let fieldCode = filedParts[1];//字段code

      let currentChildren = tplData.form.form_data.children[tableCode] || [];
      if (rowIndex === undefined) {
        //主表触发，更新子表所有行
        currentChildren.forEach((c, index) => {
          _updateFieldData({
            tplData: tplData,
            fieldValue: data[fieldPath],
            fieldCode: fieldCode,
            rowIndex: index,
            groupCode: tableCode
          });//更新字段数据、data_range、fieldSources、说明文字、计算数据源
        });
      } else {
        //子表触发，更新子表当前行
        _updateFieldData({
          tplData: tplData,
          fieldValue: data[fieldPath],
          fieldCode: fieldCode,
          rowIndex: rowIndex,
          groupCode: tableCode
        });//更新字段数据、data_range、fieldSources、说明文字、计算数据源
      }
    } else {
      console.warn("格式异常的字段：" + fieldPath);
    }
  } else {//主表更新
    _updateFieldData({
      tplData: tplData,
      fieldValue: data[fieldPath],
      fieldCode: fieldPath
    });//更新字段数据、data_range、fieldSources、说明文字、计算数据源
  }
}

/**
 * 主表字段和子表字段更新 tplData.form_data tplData.form.data_range tplData.form.form_data.fieldSources 
 * 以及触发联动计算
*/
function _updateFieldData({
  tplData,
  fieldValue,//后端计算出来的结果
  fieldCode,//字段code
  rowIndex,//更新的行索引
  groupCode//子表code，主表不传
}){
  let fullFieldPath;
  if(rowIndex === undefined){//主表
    fullFieldPath = "form.form_data.main." + fieldCode;//先拼接主表字段的路径，字段在form_data内的路径
  }else{//子表
    fullFieldPath = "form.form_data.children." + groupCode + "[" + rowIndex + "]." + fieldCode;
  }

  //1.根据后端返回的值，更新 form.data_range 和 form.form_data.fieldSources 选项
  fieldValue = updateDataRange({
    tplData: tplData,
    fieldValue: fieldValue,
    fieldCode: fieldCode,
    rowIndex: rowIndex,//更新的行索引
    groupCode: groupCode//子表code，主表不传
  });
  //2.更新字段在tplData.form.form_data内的值
  set(tplData, fullFieldPath, fieldValue);
  //3.更新前端计算依赖的数据源
  tplData.calculateFormData = mergecalculateFormData(tplData);
  //4.触发主表字段组件更新-只更新组件UI
  eventBus.publish(updateField + fullFieldPath, fieldValue);
  //5.触发字段计算
  eventBus.publish("field.triggerCalculate", fullFieldPath, fieldValue, rowIndex);
}

/**
 * 更新select CheckBox radio的选项数据
 * 包括form.data_range 和 form.form_data.fieldSources 选项
 * */
export function updateDataRange({
  tplData,
  fieldValue,
  fieldCode,//字段code
  rowIndex,//更新的行索引
  groupCode//子表code，主表不传
}){
  let fieldData = null;
  if(rowIndex === undefined){//主表
    fieldData = tplData.form.data_define.main.fields.find(function(mainField){
      return mainField.code === fieldCode;
    });//找到需要更新的主表字段
  }else{
    //找到子表对应的列
    tplData.form.data_define.children.find(function(group){
      if(group.code === groupCode){//1.先找到分组
        return group.fields.find(function(subTableField){
          if(subTableField.code === fieldCode){//2.再找到列
            fieldData = subTableField
            return true
          }
        })
      }else{
        return false;
      }
    });
  }
  if(!fieldData){
    //字段在业务对象内部存在
    if(groupCode){
      console.warn("业务对象内，不存在字段" + groupCode + "." + fieldCode);
    }else{
      console.warn("业务对象内，不存在字段" + fieldCode);
    }
    return fieldValue;
  }
  
  //字段类型是 下拉 chexkbox radio hyperlink，则对后端返回的值进行处理
  if(~["dropdown", "checkbox_group", "radio", "hyperlink"].indexOf(fieldData.type)){
    if (Array.isArray(fieldValue)) {//后端提供的数据是否为数组
      /*
        如果为数组，fieldValue 正确格式为（radio select）
        情况1：[
          [1,"实际值1","显示值1","说明1"],
          [0,"实际值0","显示值0","说明2"]
        ]
        情况2：[]
        情况3：[undefined]
        情况4：[1,2,4]

        checkbox正确格式为
        [
          [1,"实际值1","说明"],
          [0,"实际值0"]
        ]

        hyperlink正确格式为
        [
          ["显示文本1","pc链接地址1","移动链接地址1"],
          ["显示文本1","pc链接地址1","移动链接地址1"],
        ]
      */
      let value = null;
      if(Array.isArray(fieldValue[0])){//数组的第一个值是数组，处理默认值，情况1
        let defaultValueArray = fieldValue.find((v) => v[0] == 1) || [];
        
        if(fieldData.type === "checkbox_group"){//checkbox从索引1里面取
          value =[];
          fieldValue.forEach((v) => {
            if(v[0] == 1){
              if(v[1] === undefined || v[1] === null){//兼容异常数据
                console.warn("get-field-data接口返回值checkbox后端提供的数据异常，字段code为：" + groupCode + "." +fieldCode)
              }else{
                value.push(v[1]);
              }
            }
          });
          value = value.join(",");
          if(value === ""){//兼容异常数据，如果给的数据没选中项，CheckBox的value设置为null，保持统一
            value = null;
          }
        }else if(fieldData.type ==="hyperlink"){//超链接
          value = null;//超链接不能有值，是从form.data_range 和 form.form_data.fieldSources 数据内循环取的值
        }else{//radio select 从索引2里面取
          if (defaultValueArray[2] !== undefined) {
            value = defaultValueArray[2];
          }
        }
      }else if(fieldValue[0] === undefined){//否则后端返回的是空数组，情况2和3
        //联动后，后端返回的联动结果可能是个[], fieldValue[0]是没有值的，这种情况把value重置为null
        value = null;
      }else{//情况4，异常数据暂时不兼容
        console.warn("下拉联动返回值异常，字段code为：" + groupCode + "." + fieldCode +"，后端返回的数据为：", fieldValue);
      }
      
      
      let rangePath = "form.data_range.main." + fieldCode;
      let sourcePath = "form.form_data.fieldSources.main." + fieldCode;
      let remarkPath = "refreshRemarkTip.form.data_range.main." + fieldCode;
      if (rowIndex !== undefined) {//更新字段包含行索引，表示更新的是子表
        //子表字段
        rangePath = "form.data_range.children." + groupCode + "." + fieldCode; //固定文本每行都是一样的，不需要用rowIndex去查找每行
        sourcePath = "form.form_data.fieldSources.children." + groupCode + "[" + rowIndex + "]." + fieldCode; //关键字每行都不一样，需要用rowIndex找对应行的数据
        remarkPath = "refreshRemarkTip.form.data_range.children." + groupCode + "." + fieldCode;
      }
      //1.更新 form.data_range 和 form.form_data.fieldSources 选项
      set(tplData, rangePath, fieldValue);
      set(tplData, sourcePath, fieldValue);

      //2.更新说明文字
      eventBus.publishAsync(remarkPath);
      
      //更新完选项后，返回选中的值，用于更新 tplData.form_data 内字段实际数据
      return value;
    }
  }
  

  //不满足CheckBox radio select组件，或者满足了但值不是数组时，直接返回传入的值
  return fieldValue;
}

export default function useSqlValueTrigger(tplData) {
  const cacheRef = useRef({});
  const { params, urlPrefix = "" } = useForm().root;

  /**
   * allFields 被触发字段依赖，需要更新的字段code
   * groupCode 需要更新的分组code
   * rowIndex 需要更新的行索引，主表为undefined
   * originField 触发字段的code，主表：字段code 子表：？
   */
  function getFieldData(allFields, groupCode, rowIndex, originField) {
    let query_source = {
      [tplData.form.data_define.main.code]: tplData.form.form_data.main,
    };

    //准备后端需要的数据
    let data = {
      business_id: params.business_id || "",
      package_id: params.package_id || "",
      process_id: params.process_id || "",
      query_fields: allFields,
      query_source,
      rowIndex,//触发字段的行索引，主表为undefined
    };

    if (rowIndex !== undefined) {
      //子表触发
      query_source[groupCode] = get(tplData, "form.form_data.children." + groupCode + "[" + rowIndex + "]");
    } else {
      //主表触发
      /**
       * 判断需要更新的字段，是否包含子表
       * 1.如果包含，返回结果会包含整个子表或者整个子表，数据格式为
       * {
       *  children:{
       *    子表code:[
       *      {
       *        列code1: 列值
       *        列code2: 列值
       *      },
       *      {子表第2行数据}
       *      ...其他行数据
       *    ]
       *  },
       *  main:{
       *     字段code1: 字段值
       *     字段code2: 字段值
       *      ...其他字段
       *  }
       * }
       * 2.如果不包含，返回结果只包含需要更新的字段值
       * 如果是子表
       * {
       *    列code1: 列值
       *    列code2: 列值
       * }
       * 如果是主表
       * {
       *     字段code1: 字段值
       *     字段code2: 字段值
       *     ...其他字段
       * }
      */
      allFields.forEach(function(fieldPath){
        const filedParts = fieldPath.split(".");
        if(filedParts.length === 2){//如果存在需要更新的字段是子表列
          let tableCode = filedParts[0];//子表code
          if(!data.query_tables){
            data.query_tables = {};
          }
          if(!data.query_tables[tableCode]){
            data.query_tables[tableCode] = get(tplData, "form.form_data.children." + tableCode);//给请求参数追加对应子表的所有数据
          }
        }
      })
    }

    data.originField = originField || "";//触发联动的字段

    request({
      url: urlPrefix + "/flowinstance/approval/get-field-data",
      method: "POST",
      data: data,
    }).then(function (result) {
      if (result.data && Object.prototype.toString.call(result.data) === "[object Object]") {

        if(data.query_tables){//如果是更新整个子表 | 整个主表
          //1.更新子表
          if(result.data.children &&  Object.prototype.toString.call(result.data.children) === "[object Object]"){
            Object.keys(result.data.children).forEach((tableCode)=>{
              let tableData = result.data.children[tableCode];//子表数据，数组，包含多行
              if(Array.isArray(tableData) ){
                tableData.forEach((row, i)=>{//循环子表行，每行包含多个列信息
                  if(Object.prototype.toString.call(row) === "[object Object]"){
                      Object.keys(row).forEach(fieldPath=>{//遍历列数据，循环更新每个单元格
                        _updateField({
                          fieldPath: fieldPath,
                          tplData: tplData,
                          rowIndex: i,//子表更新，需要传入行索引
                          data: row,
                          groupCode: tableCode
                        });
                      })
                  }

                })
              }
            })
          }
          //2.更新主表
          if(result.data.main &&  Object.prototype.toString.call(result.data.main) === "[object Object]"){
            Object.keys(result.data.main).forEach((fieldPath)=>{
              _updateField({
                fieldPath: fieldPath,
                tplData: tplData,
                // rowIndex: rowIndex,//更新主表不需要行索引
                data: result.data.main
              });
            })
          }
        }else{
          Object.keys(result.data).forEach((fieldPath) => {
            _updateField({
              fieldPath: fieldPath,
              tplData: tplData,
              rowIndex: rowIndex,//这里的行索引，由触发的字段传入，主表触发为undefined，子表触发为字段所在行索引
              data: result.data
            })  
          });
        }
        
        saveformDataObject({
          tplData: tplData,
          params: params
        });//更新流程中心的业务数据信息

      }
    });
  }
  /**
   * 监听字段blur事件来触发规则
   * field 触发的字段path 主表"form.form_data.main.字段Code" 子表 主表"form.form_data.children.分组code.字段Code"
   * value 触发时，触发字段的value
   * rowIndex 触发字段的行索引，主表为 undefined
   */
  useSubscribe("field.blur", (field = "", value, rowIndex) => {
    //主表filed不会带.  子表code group以.隔开
    if (cacheRef.current[field] !== false) {
      let allFields = [];//被触发字段依赖，需要更新的字段code
      //按顺序收集依赖
      function addTo(targetFields) {
        for (let index = 0; index < targetFields.length; index++) {
          const targetField = targetFields[index];
          if (~allFields.indexOf(targetField)) {
            break;
          }
          allFields.push(targetField);
          let nextFields = tplData.form.triggers[`[${targetField}]`];
          if (nextFields) {
            addTo(nextFields);
          }
        }
      }

      let originField;
      let groupCode;
      //主表
      if (field.startsWith("form.form_data.main.")) {
        originField = field.replace("form.form_data.main.", "");
      } else if (field.startsWith("form.form_data.children.")) {
        //子表
        originField = field.replace("form.form_data.children.", "").replace(/\[.*\]/, "");
        const filedParts = originField.split(".");
        if (filedParts.length === 2) {
          groupCode = filedParts[0];
        }
      }
      let fields = tplData.form.triggers[`[${originField}]`];
      if (fields) {
        //按顺序收集依赖
        addTo(fields);
        getFieldData(allFields, groupCode, rowIndex, originField);
      } else {
        cacheRef.current[field] = false;
      }
    }
  });

  //子表新增行时触发规则
  useSubscribe("group.row.add",(allFields, groupCode, rowIndex)=>{
    getFieldData(allFields, groupCode, rowIndex);
  })
}
